package jlfm.lastfm.apps.recorder;

import jlfm.lastfm.client.impl.simple.ProxyConfiguration;
import jlfm.lastfm.station.LastFmGlobalTagStation;
import jlfm.lastfm.station.LastFmNeighbourStation;
import jlfm.lastfm.station.LastFmRecommendationsStation;
import jlfm.lastfm.station.LastFmSimilarArtistStation;
import jlfm.lastfm.station.LastFmStation;
import jlfm.lastfm.station.LastFmUrlStation;
import jlfm.lastfm.station.LastFmUserRelatedStation;
import jlfm.lastfm.station.LastFmUserStation;

import com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt.GetOpt;
import com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt.GetOptsException;

public class RecordOptionParser {

	private static final String OPTIONS = "hu:p:f:t:s:U:DPm:H:";

	private static boolean stationAlreadySet = false;

	public static RecorderOptions createRecorderOptions(String[] args)
			throws OptionsParsingException {

		RecorderOptions recorderOptions = new RecorderOptions();
		GetOpt getOpt = new GetOpt(args, OPTIONS);

		int opt = -1;
		try {
			while ((opt = getOpt.getNextOption()) != -1) {
				switch (opt) {
				case 'u':
					recorderOptions.setUserName(getOpt.getOptionArg());
					break;
				case 'p':
					recorderOptions.setPw(getOpt.getOptionArg());
					break;
				case 'f':
					recorderOptions.setFileNamePattern(getOpt.getOptionArg());
					break;
				case 't':
					setStation(recorderOptions, new LastFmGlobalTagStation(
							getOpt.getOptionArg()));
					break;
				case 's':
					setStation(recorderOptions, new LastFmSimilarArtistStation(
							getOpt.getOptionArg()));
					break;
				// TODO///////-->
				case 'n':
					setStation(recorderOptions, new LastFmNeighbourStation(
							getOpt.getOptionArg()));
					break;
				case 'r':
					setStation(recorderOptions,
							new LastFmRecommendationsStation(getOpt
									.getOptionArg()));
					break;
				case 'X':
					setStation(recorderOptions, new LastFmUserStation(getOpt
							.getOptionArg()));
					break;
				// ////////////-->
				case 'U':
					setStation(recorderOptions, new LastFmUrlStation(getOpt
							.getOptionArg()));
					break;

				case 'D':
					/* Disable MusicBrainz ID3 */
					recorderOptions.setMusicBrainzEnabled(false);
					break;
				case 'P':
					/* Enable Progress view */
					recorderOptions.setShowProgress(true);
					break;
				case 'm':
					/* Enable Progress view */
					recorderOptions.setM3uFileName(getOpt.getOptionArg());
					break;
				case 'h':
					recorderOptions.setPrintHelp(true);
					break;
				case 'H':
					recorderOptions
							.setProxyConfiguration(getProxyConfigurationFromOptionArg(getOpt
									.getOptionArg()));
					break;
				}
			}
			if (recorderOptions.getStation() instanceof LastFmUserRelatedStation) {
				LastFmUserRelatedStation s = (LastFmUserRelatedStation) recorderOptions
						.getStation();
				if (s.getUserName() == null || s.getUserName().length() == 0) {
					s.setUserName(recorderOptions.getUserName());
				}
			}
		} catch (GetOptsException e) {
			throw new OptionsParsingException(e);
		}

		return recorderOptions;
	}

	/**
	 * @param optionArg
	 * @return
	 */
	private static ProxyConfiguration getProxyConfigurationFromOptionArg(
			String optionArg) {
		boolean parsingError = false;
		String proxyHost = null;
		int proxyPort = 0;

		if (optionArg.indexOf(":") >= 0) {
			proxyHost = optionArg.substring(0, optionArg.indexOf(":"));
			String proxyPortString = optionArg
					.substring(optionArg.indexOf(":") + 1);
			try {
				proxyPort = new Integer(proxyPortString).intValue();
			} catch (NumberFormatException e) {
				parsingError = true;
			}
		} else {
			parsingError = true;
		}
		if (parsingError) {
			throw new OptionsParsingException(
					"http proxy must be defined as <proxyhost>:<proxyport>!");
		}

		return new ProxyConfiguration(proxyHost, proxyPort);

	}

	public static void printHelp() {
		final String nl = "\n";
		String help = "";
		help += "Aufruf: lfmripper [-u <user>] [-p <password>] [-f <filename-pattern>]"
				+ nl
				+ "[-t <global-tag> | -s <similar-artist>] [-m <m3u-output-file>]"
				+ " [-D] [-P]";
		help += nl + nl + "Options:" + nl;

		help += getOptInfo("-u <user>", "lastFm user name");
		help += getOptInfo("-p <password>", "lastFm user password");
		help += getOptInfo(
				"-f <filename-pattern>",
				"use <filename-pattern> as pattern for creating mp3 files. Following variables are supported:");
		help += getOptInfo("", "%Artist     name of arist");
		help += getOptInfo("", "%Album      name of album");
		help += getOptInfo("", "%Track      name of actual track");
		help += getOptInfo("", "%Station    name of lastFm station");
		help += getOptInfo("-t <tag>",
				"record global lastfm station specified by <tag>");
		help += getOptInfo("-s <artist>",
				"record music similar to music of <artist>");
		// ////////
		help += getOptInfo("-n [<user>]",
				"record music from neighbour station of <user>");
		help += getOptInfo("-r [<user>]", "record recommended music for <user>");
		help += getOptInfo("-X [<user>]", "record personal station of <user>");
		help += getOptInfo("-U <lastfm-url>",
				"record station locate by URL (e.g. lastfm://globaltags/Rock)");
		// ///////
		help += getOptInfo("-m <m3ufile>",
				"save m3u playlist for recorded tracks");
		help += getOptInfo("-D",
				"don't use musicbrainz service for retrieving ID3 tag information");
		help += getOptInfo("-P", "print recording progress for each track");
		help += getOptInfo("-H <proxyhost>:<proxyport>",
				"use http proxy <proxyhost> with port <proxyport>");
		help += getOptInfo("-h", "print this help");

		System.out.println(help);
	}

	public static void main(String[] args) {
		printHelp();
	}

	private static String getOptInfo(String opt, String help) {
		final int spaceLeft = 25;
		final int spaceRight = 40;
		String line = "  " + opt + " ";
		for (int i = line.length(); i < spaceLeft; i++) {
			line += " ";
		}
		if (help.length() > spaceRight) {
			String temp = help.substring(0, spaceRight);
			int z = temp.lastIndexOf(" ");
			temp = help.substring(0, z);
			line += temp;
			line += "\n" + getOptInfo("", help.substring(z + 1));
			return line;
		} else {
			line += help;
		}
		return line + "\n\n";
	}

	private static void setStation(RecorderOptions recorderOptions,
			LastFmStation station) {
		if (stationAlreadySet) {
			throw new OptionsParsingException("Station already set!!");
		}
		recorderOptions.setStation(station);
		stationAlreadySet = true;
	}
}
